package com.weilele.library.download.impl.downloadmanager

import android.app.DownloadManager
import android.content.*
import android.database.Cursor
import android.net.Uri
import androidx.core.database.getLongOrNull
import androidx.core.database.getStringOrNull
import com.weilele.library.download.IMvvmDownload
import com.weilele.library.download.impl.BaseMvvmDownload
import com.weilele.mvvm.utils.coroutine.switchToUi
import com.weilele.mvvm.utils.logI
import com.weilele.mvvm.utils.printIntent
import kotlinx.coroutines.CoroutineScope


class DownloadManagerImpl(private val context: Context) : BaseMvvmDownload() {
    /**
     * 系统下载管理器
     */
    private val manager by lazy { context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager }

    /**
     * 数据库查询
     */
    private val contentResolver by lazy { context.contentResolver }

    /**
     * 监听广播
     */
    private val downLoadBroadcast by lazy { DownLoadBroadcast() }

    /**
     * 保存下载集合
     */
    private val downloadsMap = HashMap<String, IMvvmDownload.Request>()


    override fun startDownload(
        request: IMvvmDownload.Request
    ): Long {
        val downloadRequest = DownloadManager.Request(request.uri)
        //设置漫游条件下是否可以下载
        downloadRequest.setAllowedOverRoaming(false)
        //在通知栏中显示，默认就是显示的
        downloadRequest.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE)
        //设置通知标题
        downloadRequest.setTitle(request.title/*通知标题，随意修改*/)
        //设置文件类型
        downloadRequest.setMimeType(request.mineType)
        //设置通知标题message
        downloadRequest.setDescription(request.description/*"新版zip下载中..."*/)
        //设置文件存放路径
        if (request.savePublic) {
            downloadRequest.setDestinationInExternalPublicDir(request.dirType, request.subPath)
        } else {
            downloadRequest.setDestinationInExternalFilesDir(
                context,
                request.dirType,
                request.subPath
            )
        }
        //将下载请求加入下载队列，加入下载队列后会给该任务返回一个long型的id，通过该id可以取消任务，重启任务、获取下载的文件等等
        request._id = manager.enqueue(downloadRequest)
        downloadsMap[request.uri.toString()] = request
        listenersForEach {
            it.onUpdateList(downloadsMap.values.toMutableList())
            it.onUpdate(request)
        }
        return request.id
    }

    override fun pauseDownload(vararg ids: Long): Boolean {
        return false
    }

    override fun resumeDownload(vararg ids: Long): Boolean {
        return false
    }

    override fun deleteDownload(vararg ids: Long): Boolean {
        val count = ids.count()
        if (count == 0) {
            return false
        }
        return manager.remove(*ids) > 0
    }

    override fun queryDownload(status: Int): MutableList<IMvvmDownload.Request> {
        return queryAllDownload(DownloadManager.Query().setFilterByStatus(status))
    }

    override fun queryDownload(vararg ids: Long): MutableList<IMvvmDownload.Request> {
        return queryAllDownload(DownloadManager.Query().setFilterById(*ids))
    }

    private fun queryAllDownload(query: DownloadManager.Query): MutableList<IMvvmDownload.Request> {
        var cursor: Cursor? = null
        val requests = mutableListOf<IMvvmDownload.Request>()
        try {
            cursor = manager.query(query)
            if (cursor?.moveToNext() == true) {
                val id =
                    cursor.getLongOrNull(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_ID))
                        ?: -1
                if (id >= 0) {
                    val uri =
                        cursor.getStringOrNull(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_URI))
                            ?: ""
                    val title =
                        cursor.getStringOrNull(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_TITLE))
                            ?: ""
                    val description =
                        cursor.getStringOrNull(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_DESCRIPTION))

                    val type =
                        cursor.getStringOrNull(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_MEDIA_TYPE))
                    val path =
                        cursor.getStringOrNull(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_LOCAL_URI))
                            ?: ""
                    val request = downloadsMap[uri] ?: IMvvmDownload.Request(
                        Uri.parse(uri),
                        title,
                        type,
                        false,
                        path,
                        path,
                        description
                    ).also {
                        downloadsMap[uri] = it
                    }
                    request._id = id
                    request._downloadedSize =
                        cursor.getLong(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR))
                    request._totalSize =
                        cursor.getLong(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_TOTAL_SIZE_BYTES))
                    request._status =
                        cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS))
                    requests.add(request)
                }
            }
        } finally {
            cursor?.close()
        }
        return requests
    }

    override suspend fun onTick(scope: CoroutineScope) {
        val downloads = queryAllDownload(DownloadManager.Query())
        switchToUi {
            listenersForEach {
                it.onUpdateList(downloads)
                downloads.forEach { request ->
                    it.onUpdate(request)
                }
            }
        }
    }


    override fun onCreate() {
        super.onCreate()
        context.registerReceiver(downLoadBroadcast, IntentFilter().apply {
            addAction(DownloadManager.ACTION_DOWNLOAD_COMPLETE)
            addAction(DownloadManager.ACTION_DOWNLOAD_COMPLETE)
            addAction(DownloadManager.ACTION_VIEW_DOWNLOADS)
        })
    }

    override fun onDestroy() {
        super.onDestroy()
        context.unregisterReceiver(downLoadBroadcast)
    }

    /**
     * 接受下载完成广播
     */
    private inner class DownLoadBroadcast : BroadcastReceiver() {
        override fun onReceive(context: Context?, intent: Intent) {
            logI { "$it--->action:${intent.action}" }
            printIntent { intent }
            when (intent.action) {
                DownloadManager.ACTION_DOWNLOAD_COMPLETE -> {//下载完成
                    val downId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1)
                    queryDownload(downId).firstOrNull()?.let { request: IMvvmDownload.Request ->
                        listenersForEach {
                            it.onUpdate(request)
                        }
                    }
                }
                DownloadManager.ACTION_NOTIFICATION_CLICKED -> {
                    val downIds =
                        intent.getLongArrayExtra(DownloadManager.EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS)
                    if (downIds != null) {
                        val downs = queryDownload(*downIds)
                        listenersForEach {
                            it.onNotificationClicked(downs)
                        }
                    }
                }
                DownloadManager.ACTION_VIEW_DOWNLOADS -> {

                }
            }
        }
    }

}